/*
 * Copyright (c) Jan Šlahora (${USER}) - 2012.
 * Created in IntelliJ IDEA 10.5
 */

package statistics;

import GUIComponents.Tabulka;
import text.DejCetnosti;

import javax.swing.*;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;
import javax.swing.text.html.HTML;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

/*
*   File Aliterace 
*   in package statistics
*   was created by slaha
*   on 13.3.12 at 11:03.
*
*/
public class Aliterace extends Samohlasky {
  private String text;
  private HashMap<Character, Double> pravdepodobnosti;
  private String[] verse;

  // tabulka
  private JTable tabulka;

  //pro tabulku
  private double[] KA;
  private ArrayList[] fonemy;
  private int[] n;
  private ArrayList[] Kx;
  private double[] P;

  public Aliterace(String text) {
    this.text = text;
    ArrayList<String> al = new ArrayList<>();
    al.add(text);
    DejCetnosti.CetnostZnaku cZ = new DejCetnosti().dejCetnostZnaku(al, false, true);
    Tabulka t = new Tabulka(null, cZ.getHm()); 
    pravdepodobnosti = dejPravdepodobnosti(t.getData());
    verse = dejVerse();
    KA = new double[verse.length];
    P = new double[verse.length];
    n = new int[verse.length];
    fonemy = new ArrayList[verse.length];
    Kx = new ArrayList[verse.length];
    spocitejAliteraci();

    tabulka = dejTabulku();
  }

  private void spocitejAliteraci() {
    //int xxx = 0;
    for (int i = 0; i < verse.length; i++) {
      String[] slova = dejSlova(verse[i]);

      n[i] = slova.length;

      HashMap<Character, Integer> hm = dejAliteraciVerse(slova);

      fonemy[i] = naplnArrayList(hm, true);
      Kx[i] = naplnArrayList(hm, false);
      double suma = 0;
      if (hm.size() == 0) {
        KA[i] = 0;
        P[i] = -1;
        continue;
      }
      else if (hm.size() == 1)
      {
        int n = slova.length;
        int r = hm.values().toArray(new Integer[0])[0];
        char c = hm.keySet().toArray(new Character[0])[0];
        double p = pravdepodobnosti.get(c);
        double q = 1 - p;
        while (r <= n) {
          double kombinacniCislo = 0;
          double clen = 0;
          try {
            kombinacniCislo = Pocitani.kombinacniCislo(n, r);
            clen = kombinacniCislo * Math.pow(p, r) * Math.pow(q , (n-r));
          } catch (Exception e) {
            System.err.println("Can't compute");
            System.err.println(e);
          }
          if (clen != 0) {
            suma += clen;
          }
        r++;
        }
      }
      else if (hm.size() == 2)
      {
        int n = slova.length;
        int[] pocetVyskytu = Pocitani.convertIntegers(new ArrayList<>(hm.values()));
        Character[] vyskytujiciSeZnaky = hm.keySet().toArray(new Character[0]);

        double p1 = pravdepodobnosti.get(vyskytujiciSeZnaky[0]);
        double p2 = pravdepodobnosti.get(vyskytujiciSeZnaky[1]);
        double dolnek = 1 - p1 - p2;

        int k1 = pocetVyskytu[0];
        int k2 = pocetVyskytu[1];
        int k3 = n - k1 - k2;

        suma += Pocitani.kombinacniCislo(n, pocetVyskytu) * Math.pow(p1, k1) * Math.pow(p2, k2) * Math.pow(dolnek, k3);

        int l1 = k1;
        int l2 = k2;
        int l3 = n - k1 - k2;
        while (l1 + l2 < n && l3 > 0) {
          l1++;
          l3--;
          pocetVyskytu[0] = l1;
          pocetVyskytu[1] = l2;
          suma += Pocitani.kombinacniCislo(n, pocetVyskytu) * Math.pow(p1, l1) * Math.pow(p2, l2) * Math.pow(dolnek, l3);
        }
        l1 = k1;
        l3 = n - k1 - k2;
        while (l1 + l2 < n && l3 > 0) {
          l2++;
          l3--;
          pocetVyskytu[0] = l1;
          pocetVyskytu[1] = l2;
          suma += Pocitani.kombinacniCislo(n, pocetVyskytu) * Math.pow(p1, l1) * Math.pow(p2, l2) * Math.pow(dolnek, l3);
        }
        l2 = k2;
        l3 = n - k1 - k2;
        while (((l1+1) + (l2+1) < n) && (l3 > 0)) {
          l1++;
          l2++;
          l3 -= 2;
          pocetVyskytu[0] = l1;
          pocetVyskytu[1] = l2;
          suma += Pocitani.kombinacniCislo(n, pocetVyskytu) * Math.pow(p1, l1) * Math.pow(p2, l2) * Math.pow(dolnek, l3);
        }
      }
      if (suma < 0.05) {
        KA[i] = 100 * (0.05 - suma);
        P[i] = suma;
      } else {
        KA[i] = 0;
        P[i] = -1;
      }
    }
  }

  private HashMap<Character, Integer> dejAliteraciVerse(String[] slova) {
    HashMap<Character, Integer> hm = new HashMap<>();

    for (int i = 0; i < slova.length; i++) {
      char c = Character.toLowerCase(slova[i].charAt(0));

      if (hm.containsKey(c)) {
        continue;
      } else {
        int pocet = 1;
        for (int j = i + 1; j < slova.length; j++) {
          char dalsi = Character.toLowerCase(slova[j].charAt(0));
          if (c == dalsi) {
            pocet++;
          }
        }
        if (pocet > 1) {
          hm.put(c, pocet);
        }
      }
    }

    return hm;
  }

  private String[] dejSlova(String s) {
    return s.split(" ");
  }

  private String[] dejVerse() {
    String[] lines = text.split("\r\n|\r|\n");
    List<String> list = new ArrayList<>(Arrays.asList(lines));
    list.removeAll(Arrays.asList(""));
    /*for (String s : list) {
      if (s.length() == 0) {
        list.removeA(s);
      }
    }*/

    return list.toArray(new String[0]);
    //return lines;
  }

  private JTable dejTabulku() {
    Object rowData[][] = dejDataTabulce();
    String[] hlavicka = {"Verš", "Fonémy", "n", "k1, k2", "P", "KA"};
    JTable t = new JTable(rowData, hlavicka);
    return t;
  }

  private Object[][] dejDataTabulce() {
    Object[][] o = new Object[verse.length+1][6];

    for (int i = 0; i < verse.length; i++) {
      o[i][0] = i + 1;
      o[i][1] = arrayListToString(fonemy[i]);
      o[i][2] = n[i];
      o[i][3] = arrayListToString(Kx[i]);
      o[i][4] = P[i] == -1 ? "-" : P[i];
      o[i][5] = KA[i];
    }

    o[verse.length][5] = dejKAString();

    return o;
  }

  private ArrayList naplnArrayList(HashMap hm, boolean keys) {
    ArrayList<Object> al = new ArrayList<>();
    if (keys) {
      for (Object c : hm.keySet()) {
        al.add(c);
      }
    } else {
      for (Object c : hm.values()) {
        al.add(c);
      }
    }
    return al;
  }

  private String arrayListToString(ArrayList al) {
    String s = "";
    if (!al.isEmpty()) {
      for (Object o : al) {
        s += o.toString();
        s += "; ";
      }
      return s.substring(0, s.length() - 2);
    } else {
      return "-";
    }


  }

  public JTable getTabulka() {
    return tabulka;
  }

  private String dejKAString() {
    String r = "KA = ";

    double sumaKA = 0d;
    for (double ka : KA) {
      sumaKA += ka;
    }

    double celkoveKA = sumaKA / KA.length;



    r += ((double) (Math.round(sumaKA*100)) / 100) + "/" + KA.length;

    r += " = " + (double) (Math.round(celkoveKA*100)) / 100;
    return r;
  }
}
